#include "surface.h"


using namespace std;

Surface::Surface(int slices,int stacks)
{
	m_slices = slices;
	m_stacks = stacks;

	m_polygonModeFace = GL_FRONT_AND_BACK;
	m_polygonMode =  GL_FILL;

	//Cuando no se le pasa una textura, el default es falso.
	m_showTexture = false;

	m_texture = NULL;
	m_textureLoader = NULL;
	m_texturePath = NULL;
}

Surface::Surface(const char* texturePath,int slices,int stacks)
{
	// Cuando se le pasa la textura, el default es true.
	m_showTexture = true;
	m_texturePath = texturePath;

	m_slices = slices;
	m_stacks = stacks;

	m_polygonModeFace = GL_FRONT_AND_BACK;
	m_polygonMode =  GL_FILL;

	m_texture = NULL;
	m_textureLoader = NULL;
}

Surface::~Surface()
{
	if (m_textureLoader!= NULL&&m_texture!=NULL)
	{
		m_textureLoader->FreeTexture(m_texture);
	}

	if (m_textureLoader!=NULL)
		delete m_textureLoader;

	if (m_texture!=NULL)
		delete m_texture;
}

void Surface::Init()
{
	// Se creo este init, porque necesita estar todo seteado en opengl
	// para llamar a loadtexture de TextureLoader, no puedo hacerlo en el constructor.

	// Si se especifico una textura para la superficie.
	if (strlen(m_texturePath) > 0)
	{
		m_textureLoader = new TextureLoader();
		m_texture = new glTexture();

		char* textureName = new char[strlen(m_texturePath)];
		strcpy(textureName,m_texturePath);
		m_textureLoader->LoadTextureFromDisk(textureName,m_texture);
		//delete[] textureName;
	}
}

void Surface::Update(float dt)
{
	m_vertices.clear();
	m_textureCoords.clear();
	m_normals.clear();
	m_indices.clear();
	

	loadVertexArray();
	loadTextureCoordArray();
	loadNormalArray();
	loadIndexArray();

	glutPostRedisplay();
}

void Surface::SetPolygonMode(GLenum face, GLenum mode)
{
	m_polygonModeFace = face;
	m_polygonMode = mode;	
}

GLenum Surface::GetPolygonMode()
{
	return m_polygonMode;
}

void Surface::ShowTexture(bool show)
{
	m_showTexture = show;
}

void Surface::Render()
{
	glEnableClientState(GL_INDEX_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);

	// Si se seteo que muestre la textura y hay coordenadas de textura, habilito.
	if (m_showTexture&&m_textureCoords.size()>0)
	{
		glEnable(GL_TEXTURE_2D);
	}
	else
	{
		 glDisable(GL_TEXTURE_2D);
	}

	// En el caso en que haya textura.
	if (m_texture!=NULL)
	{		
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);

		//Filtros
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

		glBindTexture(GL_TEXTURE_2D,m_texture->TextureID);
	}

	 //Llena los vertices.
	if (m_vertices.size() > 0)
		glVertexPointer(3, GL_FLOAT, 0, &m_vertices[0]);

	if (m_textureCoords.size() > 0)
		glTexCoordPointer(2, GL_FLOAT, 0, &m_textureCoords[0]);

	if (m_normals.size() > 0)
		glNormalPointer(GL_FLOAT,0,&m_normals[0]);

	if (m_indices.size() > 0)
		glIndexPointer( GL_UNSIGNED_INT, 0,&m_indices[0]);	
	
	glPolygonMode(m_polygonModeFace,m_polygonMode);

	 //draw surface
	if (m_indices.size() > 0)
		glDrawElements(GL_QUADS,m_indices.size(),GL_UNSIGNED_INT,&m_indices[0]);

	glDisable(GL_TEXTURE_2D);

	 //deactivate vertex arrays after drawing
	glDisableClientState(GL_INDEX_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);
}